/**
 * 钱包工具函数
 * 用于处理与区块链钱包的交互
 */

// 检查是否安装了MetaMask钱包
export const checkIfWalletInstalled = () => {
  return typeof window.ethereum !== 'undefined';
};

// 检查是否安装了TokenPocket钱包
export const checkIfTPWalletInstalled = () => {
  return typeof window.tp !== 'undefined';
};

// 获取当前连接的钱包类型
export const getWalletType = () => {
  if (typeof window.ethereum !== 'undefined') {
    if (window.ethereum.isMetaMask) return 'MetaMask';
    if (window.ethereum.isTokenPocket) return 'TokenPocket';
  }
  if (typeof window.tp !== 'undefined') return 'TokenPocket';
  return 'Unknown';
};

/**
 * 切换网络
 * @param {Object} chainConfig 链配置
 * @returns {Promise<boolean>} 是否成功切换
 */
export const switchNetwork = async (chainConfig) => {
  if (!checkIfWalletInstalled()) {
    throw new Error('未检测到钱包插件，请安装MetaMask或TokenPocket');
  }

  try {
    // 尝试切换到指定网络
    await window.ethereum.request({
      method: 'wallet_switchEthereumChain',
      params: [{ chainId: chainConfig.chainId }],
    });
    return true;
  } catch (switchError) {
    // 如果网络不存在，尝试添加网络
    if (switchError.code === 4902) {
      try {
        await window.ethereum.request({
          method: 'wallet_addEthereumChain',
          params: [
            {
              chainId: chainConfig.chainId,
              chainName: chainConfig.chainName,
              nativeCurrency: chainConfig.nativeCurrency,
              rpcUrls: chainConfig.rpcUrls,
              blockExplorerUrls: chainConfig.blockExplorerUrls,
            },
          ],
        });
        return true;
      } catch (addError) {
        console.error('添加网络失败:', addError);
        throw new Error('添加网络失败，请手动切换网络');
      }
    } else {
      console.error('切换网络失败:', switchError);
      throw new Error('切换网络失败，请手动切换网络');
    }
  }
};

/**
 * 将10进制链ID转换为16进制
 * @param {number|string} chainId 10进制链ID
 * @returns {string} 16进制链ID，带0x前缀
 */
export const toHexChainId = (chainId) => {
  // 确保chainId是数字
  const numericChainId = parseInt(chainId, 10);
  // 转换为16进制并添加0x前缀
  return '0x' + numericChainId.toString(16);
};

/**
 * 发送代币交易
 * @param {Object} params 交易参数
 * @param {string} params.to 接收地址
 * @param {number|string} params.amount 金额
 * @param {string} params.tokenAddress 代币合约地址 (如果是ETH则为null)
 * @param {number} params.decimals 代币精度
 * @returns {Promise<string>} 交易哈希
 */
export const sendToken = async (params) => {
  if (!checkIfWalletInstalled()) {
    throw new Error('未检测到钱包插件，请安装MetaMask或TokenPocket');
  }

  try {
    const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
    const from = accounts[0];

    // 确保金额是有效的数字
    const amountNum = parseFloat(params.amount);
    if (isNaN(amountNum)) {
      throw new Error('无效的金额');
    }

    // 如果是原生代币 (ETH, BNB等)
    if (!params.tokenAddress) {
      // 计算wei值 (10^18)
      const decimals = 18; // 原生代币精度固定为18
      
      // 使用更精确的方式计算
      let amountInWei;
      try {
        // 将金额转为字符串，避免科学计数法
        const amountStr = amountNum.toString();
        
        // 检查是否有小数点
        if (amountStr.includes('.')) {
          const parts = amountStr.split('.');
          const whole = parts[0];
          let fraction = parts[1];
          
          // 处理小数部分
          if (fraction.length > decimals) {
            fraction = fraction.substring(0, decimals);
          } else {
            fraction = fraction.padEnd(decimals, '0');
          }
          
          amountInWei = whole + fraction;
        } else {
          // 整数部分后面加18个0
          amountInWei = amountStr + '0'.repeat(decimals);
        }
        
        // 移除前导0
        amountInWei = amountInWei.replace(/^0+/, '') || '0';
        
        console.log('原生代币金额(wei):', amountInWei);
      } catch (e) {
        console.error('计算wei值出错:', e);
        throw new Error('计算转账金额出错');
      }
      
      // 使用字符串处理大数值
      let hexValue;
      try {
        // 对于非常大的数值，我们需要分段处理
        if (amountInWei.length > 15) {
          // 使用自定义函数将大数字转换为16进制
          hexValue = '0x' + decimalToHex(amountInWei);
        } else {
          hexValue = '0x' + parseInt(amountInWei).toString(16);
        }
      } catch (e) {
        console.error('转换16进制出错:', e);
        throw new Error('转换金额格式出错');
      }
      
      const txParams = {
        from,
        to: params.to,
        value: hexValue,
        gas: '0x5208', // 21000 gas
      };

      console.log('发送原生代币交易参数:', txParams);
      return await window.ethereum.request({
        method: 'eth_sendTransaction',
        params: [txParams],
      });
    } 
    // 如果是ERC20代币
    else {
      // 计算代币数量
      const tokenDecimals = parseInt(params.decimals || 18, 10);
      
      // 使用更精确的方式计算
      let tokenAmountWithDecimals;
      try {
        // 将金额转为字符串，避免科学计数法
        const amountStr = amountNum.toString();
        
        // 检查是否有小数点
        if (amountStr.includes('.')) {
          const parts = amountStr.split('.');
          const whole = parts[0];
          let fraction = parts[1];
          
          // 处理小数部分
          if (fraction.length > tokenDecimals) {
            fraction = fraction.substring(0, tokenDecimals);
          } else {
            fraction = fraction.padEnd(tokenDecimals, '0');
          }
          
          tokenAmountWithDecimals = whole + fraction;
        } else {
          // 整数部分后面加上对应精度的0
          tokenAmountWithDecimals = amountStr + '0'.repeat(tokenDecimals);
        }
        
        // 移除前导0
        tokenAmountWithDecimals = tokenAmountWithDecimals.replace(/^0+/, '') || '0';
        
        console.log('代币金额(带精度):', tokenAmountWithDecimals);
      } catch (e) {
        console.error('计算代币金额出错:', e);
        throw new Error('计算转账金额出错');
      }
      
      // 使用字符串处理大数值
      let hexAmount;
      try {
        // 对于非常大的数值，我们需要分段处理
        if (tokenAmountWithDecimals.length > 15) {
          // 使用自定义函数将大数字转换为16进制
          hexAmount = decimalToHex(tokenAmountWithDecimals);
        } else {
          hexAmount = parseInt(tokenAmountWithDecimals).toString(16);
        }
      } catch (e) {
        console.error('转换16进制出错:', e);
        throw new Error('转换金额格式出错');
      }
      
      // 构建ERC20代币转账数据
      const data = '0xa9059cbb' + // transfer方法的函数选择器
                  params.to.slice(2).padStart(64, '0') + // 接收地址
                  hexAmount.padStart(64, '0'); // 金额

      const txParams = {
        from,
        to: params.tokenAddress, // 合约地址
        value: '0x0', // 0 ETH
        data,
        gas: '0x186a0', // 100000 gas
      };

      console.log('发送ERC20代币交易参数:', txParams);
      return await window.ethereum.request({
        method: 'eth_sendTransaction',
        params: [txParams],
      });
    }
  } catch (error) {
    console.error('发送交易失败:', error);
    throw new Error(error.message || '发送交易失败');
  }
};

/**
 * TokenPocket钱包转账
 * @param {Object} params 交易参数
 * @returns {Promise<any>} 交易结果
 */
export const tpTransfer = async (params) => {
  if (!checkIfTPWalletInstalled()) {
    throw new Error('未检测到TokenPocket钱包');
  }

  return new Promise((resolve, reject) => {
    window.tp.transfer({
      ...params,
      success: function(res) {
        resolve(res);
      },
      fail: function(err) {
        reject(err);
      }
    });
  });
};

/**
 * 根据钱包类型发起转账
 * @param {Object} params 交易参数
 * @returns {Promise<string>} 交易哈希或结果
 */
export const transferByWalletType = async (params) => {
  const walletType = getWalletType();
  
  if (walletType === 'TokenPocket') {
    return await tpTransfer(params);
  } else {
    return await sendToken(params);
  }
};

/**
 * 将十进制字符串转换为十六进制字符串
 * @param {string} decimalStr 十进制字符串
 * @returns {string} 十六进制字符串（不带0x前缀）
 */
export const decimalToHex = (decimalStr) => {
  if (!decimalStr || decimalStr === '0') return '0';
  
  const hexChars = '0123456789abcdef';
  let result = '';
  let decimal = decimalStr;
  
  while (decimal !== '0') {
    let remainder = 0;
    let temp = '';
    
    // 逐位除以16
    for (let i = 0; i < decimal.length; i++) {
      const digit = parseInt(decimal[i], 10) + remainder * 10;
      remainder = digit % 16;
      const quotient = Math.floor(digit / 16);
      
      if (temp !== '0' || quotient !== 0 || i === 0) {
        temp += quotient;
      }
    }
    
    result = hexChars[remainder] + result;
    decimal = temp === '' ? '0' : temp;
  }
  
  return result;
};

/**
 * 获取链配置
 * @param {Object} chainConfig 链配置对象
 * @returns {Object} 链配置
 */
export const validateChainConfig = (chainConfig) => {
  if (!chainConfig) return null;
  
  // 验证必要的字段
  if (!chainConfig.chainId || !chainConfig.chainName) {
    console.error('链配置缺少必要字段');
    return null;
  }
  
  return chainConfig;
};
